<?php
class WeixinChat
{
	private $_token = '6487607922c17a22a27f3deae18b106b';
	//消息的公共元素 发信人
	private $from_user = '';
	//收信人（本帐号）
	private $to_user = '';
	//信息类型
	private $msg_type = '';
	//收到的信息包对象
	private $msg_obj = null;
	//用户关注时回复的信息
	private $hello = '欢迎关注爱血拼微信公共帐号，您可以回复文字信息1到10获取相应条数的网站最新资讯，或者回复任何您觉得有价值的信息与我们分享，我们会及时给您反馈和解答。回复help获取更多使用帮助，也欢迎您访问我们的网站 http://ixuepin.us 。';
	//对不能匹配的消息，回复一条感谢
	private $thanks = '感谢您提供的信息，我们会尽快人工回复您。';
	//helpmsg
	private $help = '目前支持以下命令：
today 今天最新的折扣信息;
1到10的数字  指定数量的最新折扣信息;
help  显示本信息;
商品品牌、名称等任何信息，比如您可以试试“耳机”或者“硬盘”;
同时我们很愿意接收到您发给我们的任何有价值的信息，也会尽力解答您提出的疑问';
	/**
	 * 
	 * 接受系统传递的初始化字符串，分析并得到其中的用户和消息
	 * @param string $postStr
	 */
	public function __construct($postStr)
	{
		$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
		$this->msg_obj = $postObj;
		$this->from_user = $postObj->FromUserName;
        $this->to_user = $postObj->ToUserName;
        $this->msg_type = $postObj->MsgType;
        $this->_log($postStr);
	}
	/**
	 * 
	 * 根据规则返回输出字符串。
	 * $this->msg_type ：文本消息 text |图片消息 image | 地理位置消息 location | 链接消息 link | 事件推送 event(4.5支持) 
	 * @link http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97
	 */
    public function response()
    {
		$createmsg = 'response'.ucwords($this->msg_type).'msg';
		return $this->$createmsg();
    }
    
    /**
     * 
     * 暂时不自动处理文本之外的信息
     */
    public function responseImagemsg()
	{
		return $this->buildTextresponse($this->thanks);
	}
	
    /**
     * 
     * 暂时不自动处理文本之外的信息
     */
	public function responseLocationmsg()
	{
		return $this->buildTextresponse($this->thanks);
	}
	
	/**
     * 
     * 暂时不自动处理文本之外的信息
     */
	public function responseLinkmsg()
	{
		return $this->buildTextresponse($this->thanks);
	}
	/**
     * 
     * 暂时不自动处理文本之外的信息
     */
	public function responseVoicemsg()
	{
		return $this->buildTextresponse($this->thanks);
	}
	/**
     * 
     * 暂时不自动处理文本之外的信息
     */
	public function responseEventmsg()
	{
		switch($this->msg_obj->Event)
		{
			case 'subscribe':
				return $this->buildTextresponse($this->hello);
			break;
			case 'CLICK'://TODO自定义菜单点击事件
			break;
			default:
				return $this->buildTextresponse($this->thanks);
			break;
		}
	}

    
    public function responseTextmsg()
    {
    	$recvmsg = trim($this->msg_obj->Content);
    	//根据$this->from_user和$recvmsg决定回复什么消息
    	if($recvmsg == 'Hello2BizUser')
    	{
    		return $this->buildTextresponse($this->hello);
    	}
    	elseif(strtolower($recvmsg) == 'help')
    	{
    		return $this->buildTextresponse($this->help);
    	}
    	elseif(strtolower($recvmsg) == 'today')
    	{
    		$news = Article::model()->findAll("create_time>'".date('Y-m-d')."' order by id desc limit 10");
    		return $this->buildNewsresponse($news);
    	}
    	elseif(preg_match('/^\d+$/', $recvmsg))
    	{
    		$news_numbers = intval($recvmsg);
    		if($news_numbers < 1)
    			$news_numbers = 1;
    		if($news_numbers > 10)
    			$news_numbers = 10;
    		$news = Article::model()->findAll('1 order by id desc limit '.$news_numbers);
    		return $this->buildNewsresponse($news);
    	}
    	else
    	{
    		$match = addcslashes($recvmsg,'%_');
	    	$cond = new CDbCriteria();
			$cond->condition = 'tag LIKE :match';
			$cond->params = array(':match'=>"%$match%");
			$tag = Tag::model()->find($cond);
	    	if($tag)
	    	{
	    		$news = array();
	    		$article_tag_relations = Article_tag_relation::model()->findAll("tag_id={$tag->id} order by article_id desc limit 5");
		    	foreach ($article_tag_relations as $t)
				{
					if($t->article)
						$news[] = $t->article;
				}
	    		if(!empty($news))
	    		{
	    			return $this->buildNewsresponse($news);
	    		}
	    	}
	    	else 
	    	{
	    		$cond = new CDbCriteria();
	    		$cond->condition = 'title LIKE :match';
				$cond->params = array(':match'=>"%$match%");
				$cond->limit = 3;
				$cond->order = 'id desc';
				$news = Article::model()->findAll($cond);
				if(empty($news))
				{
					$cond->condition = 'url_key LIKE :match';
					$news = Article::model()->findAll($cond);
				}
	    		if(!empty($news))
	    		{
	    			return $this->buildNewsresponse($news);
	    		}
	    	}
    	}
    	//如果不是以上类型的消息，则回复一条文本
    	return $this->buildTextresponse($this->thanks);
    }
    
    public function buildTextresponse($msg)
    {
		$msg_tpl = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content><FuncFlag>0</FuncFlag></xml>";
		$return_msg = sprintf($msg_tpl, $this->from_user, $this->to_user, time(), $msg);
		$this->_log('resp:'.$return_msg);
		return $return_msg;
    }
    /**
     * 
     * 建立一个图文消息并回复。
     * @param array $msgs 传入的是网站新闻纪录的对象数组。
     */
    public function buildNewsresponse($msgs)
    {
    	$bodytpl = '<item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item>';
    	$msg_tpl = '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>%s</ArticleCount><Articles>%s</Articles><FuncFlag>1</FuncFlag></xml>';
    	$body = '';
    	foreach ($msgs as $row)
    	{
    		$pic = '';
    		if(preg_match('/<img[^>]+?src=[\'"]?([^\s\'">]+)[\'"]?[\s>]/i',$row->content,$m))
    			$pic = $m[1];//TODO要求同一域名
    		$body .= sprintf(
			    		$bodytpl,
			    		$row->title,
			    		mb_substr(strip_tags($row->content), 0,200,'utf-8'),
			    		$pic,
			    		Yii::app()->params['domain'].'/article/'.$row->url_key.'.html'
			    		);
    	}
    	$return_msg = sprintf(
    					$msg_tpl,
    					$this->from_user,
    					$this->to_user,
    					time(),
    					count($msgs),
    					$body
    					);
    	$this->_log('resp:'.$return_msg);
		return $return_msg;
    }

	private function checkSignature()
	{
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];	
        		
		$token = $this->_token;
		$tmpArr = array($token, $timestamp, $nonce);
		sort($tmpArr);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		
		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}
	public function valid()
    {
        $echoStr = $_GET["echostr"];

        //valid signature , option
        if($this->checkSignature()){
        	return $echoStr;
        }
        return '';
    }
    
    private function _log($msg)
    {
    	$logfile = dirname(dirname(__FILE__)).'/.weixin.log';
    	$log_content = date("Y-m-d H:i:s");
    	$log_content .= " : \n";
    	$log_content .= $msg;
    	$log_content .= "\n -- \n\n";
    	$handler = fopen($logfile, 'a');
    	fwrite($handler, $log_content,102400);
    	fclose($handler);
    }
}